package com.throttle.raildroid;

public class JavaRail {
	// Switch control
		// Op codes
		private static final byte SW_REQ = 0xB0-256;    // request a switch change
		private static final byte SW_REP = 0xB1-256;    // report a switch change
		// Actions
		private static final byte THROW  = 0x10;
		private static final byte CLOSE  = 0x30;
		private static final byte CLOSED = 0x10;
		// Extended
		private static final byte PUTSWITCHSTATE = 4;
		private static final byte GETSWITCHSUCC  = 6;
		private static final byte PUTSWITCHSUCC  = 7;
		private static final byte GETSWITCHSTATE = 22;
		
		// Train control
		// Op codes
		private static final byte REG_SLOT 	= 0xBA-256; // register a slot
		private static final byte BAD_SLOT 	= 0xB4-256; // insufficient slots
		private static final byte SLOT_REQ 	= 0xBF-256; // request for slot data
		private static final byte SLOT_REP 	= 0xE7-256;	// slot data response
		private static final byte SET_SPEED = 0xA0-256;	// set train speed
		private static final byte SET_MISC 	= 0xA1-256; // set direction, horn, bell, lights
		private static final byte SET_SOUND = 0xA2-256; // set/unset mute
		// Actions
		private static final byte FORWARD 	= 0x00;
		private static final byte BACKWARD 	= 0x20;
		private static final byte LIGHTSON 	= 0x10;
		private static final byte LIGHTSOFF = 0x00;		// Can have a general
		private static final byte HORNON 	= 0x02;		// "off" setting instead of
		private static final byte HORNOFF 	= 0x00;		// multiple specific ones
		private static final byte BELLON 	= 0x01;
		private static final byte BELLOFF 	= 0x00;
		private static final byte MUTEON 	= 0x08;
		private static final byte MUTEOFF 	= 0x00;
		// Extended
		private static final byte PUTTRAINSTATE = 1;
		private static final byte PUTTRAINPOS 	= 2;
		private static final byte LOCOINIT 		= 8;
		private static final byte INITOUCOME 	= 9;
		private static final byte PUTTRAININFO 	= 21;
		
		// Misc
		// Op codes
		private static final byte INPUT_REP = 0xB2-256;  // report sensor fired
		// Extended
		private static final byte PUTSECTIONSTATE 	= 3;
		private static final byte PUTSENSORSTATE 	= 5;
		private static final byte READLAYOUT 		= 10;
		private static final byte LAYOUTREP 		= 11;
		private static final byte SAVESTATE 		= 12;
		private static final byte SAVEREP 			= 13;
		private static final byte RESTORESTATE 		= 14;
		private static final byte RESTOREREP 		= 15;
		private static final byte TRYTOMOVEAGAIN 	= 16;
		private static final byte FRONTSENSORFIRED 	= 17;
		private static final byte BACKSENSORFIRED 	= 18;
		private static final byte SENSORERROR 		= 19;
		private static final byte LOSERESERVATION 	= 20;
		private static final byte EXTENDED 			= 0;
		
		
		// returns an array which gets control of a train slot
	    // RESTRICTION: will not take a train if it is in use by another throttle
	    public static byte[] makeControlTrain(int trainaddress){
	    	byte[] msg = new byte[6];
	    	msg[0] = 4;							//msg size
	    	msg[1] = 0;							//msg size cont
	    	msg[2] = REG_SLOT;					//OP code
	    	msg[3] = (byte)(trainaddress%128);	//physical train address
	    	msg[4] = (byte)(trainaddress/128);
	    	msg[4] = checkSum(msg);				//XOR checksum
	    	return msg;
	    }
	    
	    public static byte[] makeSetSpeed(int slot, int speed){
	    	byte[] msg = new byte[6];
	    	msg[0] = 4;							//msg size
	    	msg[1] = 0;							//msg size cont
	    	msg[2] = SET_SPEED;					//OP code
	    	msg[3] = (byte)slot;				//slot number
	    	msg[4] = (byte)speed;				//speed amount
	    	msg[5] = checkSum(msg);				//XOR checksum
	    	return msg;
	    }
	    
	    public static byte checkSum(byte[] msg){
	    	byte chk = 0xFF-256;
	    	for(int i=2; i<msg.length-1; i++){
	    		chk ^= msg[i];
	    	}
	    	return chk;
	    }
	    
	    public static byte[] makeChangeSwitch(int swnum, boolean state){
	    	byte[] msg = new byte[6];
	    	msg[0] = 4;							//msg size
	    	msg[1] = 0;							//msg size cont
	    	msg[2] = SW_REQ;					//OP code
	    	msg[3] = (byte)swnum;				//switchNumber (0-24)
	    	if(state)
	    		msg[4] = THROW;					//command
	    	else
	    		msg[4] = CLOSE;					//command
	    	msg[5] = checkSum(msg);				//XOR checksum
	    	return msg;
	    }
	    
	    public static byte[] makeSetMisc(int slot, boolean dir, boolean horn, boolean bell, boolean light){
	    	byte[] msg = new byte[6];
	    	byte misc = 0;
	    	msg[0] = 4;
	    	msg[1] = 0;
	    	msg[2] = SET_MISC;
	    	msg[3] = (byte)slot;
	    	if(dir)
	    		misc = (byte)(misc | BACKWARD);
	    	if(horn)
	    		misc = (byte)(misc | HORNON);
	    	if(bell)
	    		misc = (byte)(misc | BELLON);
	    	if(light)
	    		misc = (byte)(misc | LIGHTSON);
	    	msg[4] = misc;
	    	msg[5] = checkSum(msg);	
	    	return msg;
	    }

}
